package com.qf.dao;

import com.qf.pojo.Branch;
import com.qf.pojo.Contractor;
import com.qf.pojo.Developer;
import com.qf.pojo.Project;
import org.apache.ibatis.annotations.*;
import org.apache.ibatis.mapping.FetchType;

import java.util.List;

/**
 * @Description: 公用常量
 * @Data: 2022/8/25 10:21
 * @Pacakge: com.qf.dao
 * @ClassName: ProjectDao
 * @Author: fan
 * 项目数据访问接口
 */
public interface ProjectDao {
    /**
     * 查询所有项目
     * @return 项目列表
     */
    List<Project> findAllProject();

    /**
     *查询所有项目,分步查询
     * @return 项目列表
     */
    List<Project> findAllProjectByStep();

    /**
     * 查询所有项目,注解查询
     * @return 项目列表
     */
    List<Project> findAllProjectByNote();

    /**
     * 一对一用注解查询
     * @return
     */
    /*
    以下是结果映射注解@Results
        其中id:结果唯一id
            value:对应映射的字段--->属性
    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.METHOD})
    public @interface Results {
    String id() default "";
    Result[] value() default {};
    }
    value返回的结果集是一个数组Result其源码如下:
    @Result注解
    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target({})
    public @interface Result {
    boolean id() default false; //是否是主键id

    String column() default ""; //表示字段名

    String property() default "";//表示属性

    Class<?> javaType() default void.class;//java类型

    JdbcType jdbcType() default JdbcType.UNDEFINED;//jdbc类型,一般不适用

    Class<? extends TypeHandler> typeHandler() default UnknownTypeHandler.class;

    One one() default @One;//表示的一对一关系

    Many many() default @Many;//表示的是一对多关系
    }
    一对一关系@one的注解
    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target({})
    public @interface One {
    String select() default "";

    FetchType fetchType() default FetchType.DEFAULT;
    }

    一对多关系@many的注解
    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target({})
    public @interface Many {
    String select() default "";//表示调用指定方法,参数是column中的值
    FetchType fetchType() default FetchType.DEFAULT;//延迟加载策略,如果不写使用的是默认加载策略,也是立即在加载
    }
    其中FetchType源码如下
    public enum FetchType {
    LAZY,//懒加载(延迟加载)
    EAGER,//立即加载
    DEFAULT;//立即加载

    private FetchType() {
    }
    }
     */
    @Results(id = "projectByNoteMap",value = {
            @Result(column = "pid",property = "pid"),//pid的映射
            @Result(column = "pname",property = "pname"),//pname的映射
            @Result(column = "starttime",property = "starttime"),//starttime的映射
            @Result(column = "endtime",property = "endtime"),//endtime的映射
            @Result(column = "did",property = "did"),//did的映射
            @Result(column = "cid",property = "cid"),//cid的映射
            @Result(column = "updatetime",property = "updatetime"),//updatetime的映射
            @Result(column = "did",property = "developer",javaType = Developer.class,
                    one =@One(select = "com.qf.dao.DeveloperDao.findDeveloperByDidByNote",
                    fetchType = FetchType.LAZY)),
            @Result(column = "pid",property = "stages",
            many = @Many(select = "com.qf.dao.StageDao.findStageByPid",
            fetchType = FetchType.EAGER))
    })
    @Select("select * from project where status =1")
    List<Project> findAllProjectByOne();

    /**
     * 根据工程编号查询
     * @param pid 工程编号
     * @return 单个工程
     */
    /*
    @ResultMap可以引用对应的结果集
    由于其源码中value是数组,则表示可以应用多个结果集,功能可以更强大
    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.METHOD})
    public @interface ResultMap {
    String[] value();
    }
    */
    @ResultMap("projectByNoteMap")
    @Select("select * from project where pid = #{pid}")
    Project findProjectByPid(@Param("pid")int pid);

    /**
     * 新增一个行的工程
     * @param project 工程实体
     */
    void addProject(Project project);

    /**
     * 通过注解添加
     * @param project
     */
    //动态执行sql需要加入<script></script>标签
    @Insert("<script>insert into project (" +
            "<trim suffixOverrides=\",\">\n" +
            "                <if test=\"pname != null and pname != ''\">\n" +
            "                     pname,\n" +
            "                 </if>\n" +
            "                <if test=\"starttime !=null\">\n" +
            "                    starttime,\n" +
            "                </if>\n" +
            "                <if test=\"endtime != null\">\n" +
            "                    endtime,\n" +
            "                </if>\n" +
            "                <if test=\"updatetime != null\">\n" +
            "                    updatetime,\n" +
            "                </if>\n" +
            "                <if test=\"did != null and did != ''\">\n" +
            "                    did,\n" +
            "                </if>\n" +
            "                <if test=\"cid != null and cid != ''\">\n" +
            "                    cid,\n" +
            "                </if>\n" +
            "            </trim>\n" +
            "            )values (\n" +
            "            <trim suffixOverrides=\",\">\n" +
            "               <if test=\"pname != null and pname != ''\">\n" +
            "                     #{pname},\n" +
            "                 </if>\n" +
            "                <if test=\"starttime !=null\">\n" +
            "                    #{starttime},\n" +
            "                </if>\n" +
            "                <if test=\"endtime != null\">\n" +
            "                    #{endtime},\n" +
            "                </if>\n" +
            "                <if test=\"updatetime != null\">\n" +
            "                    #{updatetime},\n" +
            "                </if>\n" +
            "                <if test=\"did != null and did != ''\">\n" +
            "                    #{did},\n" +
            "                </if>\n" +
            "                <if test=\"cid != null and cid != ''\">\n" +
            "                    #{cid},\n" +
            "                </if>\n" +
            "            </trim>\n" +
            "        )</script>")
    void addProjectByNote(Project project);

    /**
     * 查询所有工程,并且携带其开发商
     * @return
     */
    @Results(id = "projectAndBranchMap",value = {
            @Result(column = "pid",property = "pid"),
            @Result(column = "pname",property = "pname"),
            @Result(column = "starttime",property = "starttime"),
            @Result(column = "endtime",property = "endtime"),
            @Result(column = "did",property = "did"),
            @Result(column = "cid",property = "cid"),
            @Result(column = "updatetime",property = "updatetime"),
            @Result(column = "pid",property = "branches",
                    many = @Many(select = "com.qf.dao.BranchDao.findBranchByPid",
                                fetchType = FetchType.EAGER)
            )
    })
    @Select("select * from project where status =1")
    List<Project> findAllProjectAndBranch();

    /**
     * 查询所有工程,并且携带承建商
     * @return
     */
    @Results(id = "projectAndContractor",value = {
            @Result(column = "pid",property = "pid"),
            @Result(column = "pname",property = "pname"),
            @Result(column = "starttime",property = "starttime"),
            @Result(column = "endtime",property = "endtime"),
            @Result(column = "did",property = "did"),
            @Result(column = "cid",property = "cid"),
            @Result(column = "updatetime",property = "updatetime"),
            @Result(column = "cid",property = "contractor",javaType = Contractor.class,
            one = @One(select="com.qf.dao.ContractorDao.findContractorByCid",
                        fetchType = FetchType.EAGER )
            )

    })
    @Select("select * from project where status = 1")
    List<Project> findProjectAndContractor();

    /**
     * 通过开发商编号查询项目
     * @param did 开发商编号
     * @return 工程实体
     */
   @ResultMap("projectAndBranchMap")
    @Select("select * from project where did = #{did} and status = 1")
    Project findProjectByDid(@Param("did")String did);
}
